package com.example.webflux_module.controller;


import com.example.webflux_module.entity.Result;
import com.example.webflux_module.entity.Results;
import com.example.webflux_module.service.EchoService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;


@Slf4j
@RestController
@RequestMapping("/controller")
public class EchoController {

    private String HOST = "http://localhost:8080";

    @Autowired
    private EchoService echoService;

    @RequestMapping("/echo_by_mvc")
    public Result echoByMvc(@RequestBody Request request) {
        String name = request.getName();
        Long sleep = request.getSleep();

        log.info("[mvc] start: {}", name);
        echoService.echo(name, sleep);
        log.info("[mvc]   end: {}", name);
        return Results.ok();
    }

    @RequestMapping("/echo_by_reactive")
    public Mono<Result> echoByReactive(@RequestBody Request request) {
        String name = request.getName();
        Long sleep = request.getSleep();

        log.info("[reactive] start: {}", name);
        Mono<Result> result = Mono.fromSupplier(() -> echoService.echo(name, sleep))
                .publishOn(Schedulers.boundedElastic());
        // echoService.echo(name);
        log.info("[reactive]   end: {}", name);
        return result;
    }

    @GetMapping(value = "/echo_by_web_client")
    public Mono<String> echoByWebClient(@RequestBody Request request) {
        String name = request.getName();
        Long sleep = request.getSleep();

        log.info("[reactive] start: {}", name);
        Mono<String> mono = Mono.just(sleep)
                .flatMap(t -> WebClient.create(HOST)
                        .get()
                        .uri("/sleep/" + sleep)
                        .retrieve()
                        .bodyToMono(String.class)).doOnNext(e -> {
                    log.info("[reactive] doOnNext: {}", name);
                });
        log.info("[reactive]   end: {}", name);
        return mono;
    }

    @Data
    public static class Request {
        private String name;
        private Long sleep;
    }
}
